/*
 * This file is part of Cadmium.
 * Copyright (C) 2007-2010 Xavier Clerc.
 *
 * Cadmium is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cadmium is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.x9c.cadmium.support;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import fr.x9c.cadmium.kernel.ByteCodeParameters;
import fr.x9c.cadmium.kernel.CadmiumException;
import fr.x9c.cadmium.kernel.Fail;
import fr.x9c.cadmium.kernel.Fatal;
import fr.x9c.cadmium.kernel.Interpreter;
import fr.x9c.cadmium.kernel.Value;
import fr.x9c.cadmium.util.RandomAccessInputStream;

/**
 * This class implements a <tt>main</tt> method executing the Cadmium interpreter. <br/>
 * Bytecode is loaded from the resource <tt>/resources/cadmium/program</tt>.
 * <br/>
 * Parameters are loaded from the resource <tt>/resources/cadmium/parameters.properties</tt>. <br/>
 * This class is the main class of jar files created using the
 * <tt>cadmium.make-application</tt> ant macro.
 *
 * @author <a href="mailto:cadmium@x9c.fr">Xavier Clerc</a>
 * @version 1.0
 * @since 1.0
 */
public final class Application {

    /** Path to 'program parameters' resource. */
    private static final String PARAMETERS = "/resources/cadmium/parameters.properties";

    /** Path to 'program bytecode' resource. */
    private static final String PROGRAM = "/resources/cadmium/program";

    /**
     * No instance of this class.
     */
    private Application() {
    } // end empty constructor

    /**
     * Executes the Cadmium interpreter. <br/>
     * Parameters as well as bytecode are loaded from jar resources.
     * @param args program arguments
     */
    public static void main(final String[] args) {
        try {
            // resources
            final InputStream propsStream =
                Application.class.getResourceAsStream(Application.PARAMETERS);
            final InputStream bytecodeStream =
                Application.class.getResourceAsStream(Application.PROGRAM);
            if ((propsStream == null) || (bytecodeStream == null)) {
                System.out.println("bytecode/parameters ressource is missing");
                System.exit(1);
            } // end if

            // interpreter parameters
            final Properties props = new Properties();
            props.load(propsStream);
            final ByteCodeParameters params =
                ByteCodeParameters.fromProperties(props,
                                                  "program",
                                                  args,
                                                  System.in,
                                                  System.out,
                                                  System.err);
            propsStream.close();

            // interpreter execution
            final RandomAccessInputStream bytecode =
                new RandomAccessInputStream(bytecodeStream);
            final Interpreter interp = new Interpreter(params,
                                                       new File("."),
                                                       bytecode);
            bytecode.close();
            final Value res = interp.execute();
            System.exit(res.isLong() ? res.asLong() : 0);
        } catch (final Fatal.Exception fatal) {
            System.out.println("fatal error: " + fatal.getMessage());
            System.exit(1);
        } catch (final IOException ioe) {
            System.out.println("i/o error: " + ioe.getMessage());
            System.exit(1);
        } catch (final CadmiumException ie) {
            final Throwable t = ie.getCause();
            if (!(t instanceof Fail.Exception)
                && !(t instanceof Fatal.Exception)) {
                System.out.println("error: " + ie.getMessage());
            } // end if
            System.exit(1);
        } catch (final Exception e) {
            System.out.println("internal error: " + e.getMessage());
            e.printStackTrace(System.err);
            System.exit(1);
        } catch (final Throwable t) {
            System.out.println("Java error: " + t.getMessage());
            t.printStackTrace(System.err);
            System.exit(1);
        } // end try/catch
    } // end method 'main(String[])'

} // end class 'Application'
